package com.igoal.service;

import java.util.List;
import java.util.Map;

import org.springframework.transaction.annotation.Transactional;

import com.igoal.dto.CommentEntryDTO;
import com.igoal.dto.FriendDTO;
import com.igoal.dto.GoalDTO;
import com.igoal.dto.UserDTO;
import com.igoal.dto.UserGoalEntryDTO;
import com.igoal.dto.UserGoalEntryDoneDTO;
import com.igoal.entity.UserGoalDone;
import com.igoal.entity.UserGoalEntry;

public interface GoalEntryManager extends GenericManager<UserGoalEntry, Long> {
	
	/**
	 * Get goal entry by its identifier
	 * @param id entry identifier
	 * @return {@link UserGoalEntryDTO}
	 */
	UserGoalEntryDTO getGoalEntryByPrimaryKey(Long id);
	
	/**
	 * Create/Update goal entry
	 * @param dto {@link UserGoalEntryDTO}
	 * @return {@link SaveResult}
	 */
	@Transactional(readOnly = false)
	int saveEntry(UserGoalEntryDTO dto);
	
	/**
	 * Remove goal entry by its identifier
	 * @param id entry identifier
	 */
	@Transactional(readOnly = false)
	int removeEntry(String username, Long id);
	
	/**
	 * Get list comments of {@link UserGoalEntry}
	 * @param entryId entry identifier
	 * @return list {@link CommentEntryDTO}
	 */
	List<CommentEntryDTO> getCommentEntry(Long entryId);
	
	/**
	 * Get entry with some information related to user
	 * @param entryId entry identifier
	 * @param currentUser related user
	 * @return entry with information
	 */
	@Transactional(readOnly = true)
	UserGoalEntryDTO getEntry(Long entryId, UserDTO currentUser);

	/**
	 * Get 'How i did it' entry with some information realted to user
	 * @param entryId entry identifier
	 * @param currentUser related user
	 * @return entry with information
	 */
	@Transactional(readOnly = true)
	UserGoalEntryDoneDTO getEntryDone(Long entryId, UserDTO currentUser);
	
	/**
	 * Get recent entries of user
	 * 
	 * @param user
	 * @return list of {@link UserGoalEntryDTO}
	 */
	@SuppressWarnings({"rawtypes" })
	List getRecentEntries(UserDTO user, UserDTO currentUser);
	
	/**
	 * Get a entry list of a specified goal
	 * 
	 * @param goalId
	 *            goal pk
	 * @return list of {@link UserGoalEntryDTO}
	 */
	@SuppressWarnings("rawtypes")
	@Transactional(readOnly = true)
	List getRecentEntries(GoalDTO goalDTO, UserDTO userDTO);
	
	/**
	 * Get an done entry of specified goal of specified user
	 * 
	 * @param goalId
	 * @param userId
	 * @return List of {@link UserGoalEntryDoneDTO}
	 */
	@Transactional(readOnly = true)
	UserGoalEntryDoneDTO getGoalDoneEntry(Long goalId, Long userId);

	/**
	 * Get a done entry list of a specified goal
	 * 
	 * @param goalId
	 * @return list of {@link UserGoalEntryDoneDTO}
	 */
	@Transactional(readOnly = true)
	List<UserGoalEntryDoneDTO> getRecentDoneEntries(Long goalId);
	
	/**
	 * Create new entry of an user goal by user
	 * 
	 * @param dto
	 *            the model of entry {@link UserGoalEntryDTO}
	 * @param user
	 *            the model of user {@link UserDTO}
	 * @return {@link SaveResult}
	 */
	@Transactional(readOnly = false)
	int createNewGoalEntry(UserGoalEntryDTO dto, UserDTO user);
	
	/**
	 * Update an entry of an user goal by user session
	 * 
	 * @param dto
	 *            the model of entry {@link UserGoalEntryDTO}
	 * @return {@link SaveResult}
	 */
	@Transactional(readOnly = false)
	int updateGoalEntry(UserGoalEntryDTO dto);

	/**
	 * Delete an entry of an user goal by user session
	 * 
	 * @param dto
	 *            the model of entry {@link UserGoalEntryDTO}
	 * @return {@link SaveResult}
	 */
	int deleteGoalEntry(String username, Long entryId);
	
	/**
	 * Create new entry done of an user goal by user
	 * 
	 * @param dto
	 *            the model of entry {@link UserGoalEntryDoneDTO}
	 * @param user
	 *            the model of user {@link UserDTO}
	 * @return {@link SaveResult}
	 */
	@Transactional(readOnly = false)
	int createNewGoalDone(UserGoalEntryDoneDTO dto, UserDTO user);

	/**
	 * Update an entry done of an user goal by user session
	 * 
	 * @param dto
	 *            the model of entry {@link UserGoalEntryDoneDTO}
	 * @return {@link SaveResult}
	 */
	@Transactional(readOnly = false)
	int updateGoalDone(UserGoalEntryDoneDTO dto);

	/**
	 * Delete an entry done of an user goal by user session
	 * 
	 * @param dto
	 *            the model of entry {@link UserGoalEntryDoneDTO}
	 * @return {@link SaveResult}
	 */
	int deleteGoalDone(UserGoalEntryDoneDTO dto);
	
	/**
	 * Count all entry of a goal
	 * @param goalId goal identifier
	 * @return number of entries
	 */
	@Transactional(readOnly = true)
	int countGoalEntry(Long goalId);
	
	/**
	 * Count how many entry that user write for a goal
	 * @param goalId goal identifier
	 * @param userId user identifier
	 * @return number of entries
	 */
	@Transactional(readOnly = true)
	int countGoalEntry(Long goalId, Long userId);
	
	/**
	 * Get all 'HOW I DID IT' entries of specified goal
	 * @param goalId goal identifier
	 * @return list {@link UserGoalDone}
	 */
	@Transactional(readOnly = true)
	List<UserGoalDone> getAllSolutions(Long goalId);
	
	/**
	 * Get goal entries by page with some criteria inside <code>MAP</code>
	 * @param criteria criteria map
	 * @param orderProperty order property name
	 * @param lastOrderPropertyValue the value that order property value must greater or less than
	 * @param before page before previous page or after
	 * @return list {@link UserGoalEntryDTO}
	 */
	@Transactional(readOnly = true)
	List<UserGoalEntryDTO> getEntriesByPaging(Map<String, Object> criteria, String orderProperty, Object lastOrderPropertyValue, boolean before);
	
	/**
	 * Get goal 'HOW I DID IT' entries by page with some criteria inside <code>MAP</code>
	 * @param criteria criteria map
	 * @param orderProperty order property name
	 * @param lastOrderPropertyValue the value that order property value must greater or less than
	 * @param before page before previous page or after
	 * @return list {@link UserGoalEntryDoneDTO}
	 */
	@Transactional(readOnly = true)
	List<UserGoalEntryDoneDTO> getDoneEntriesByPaging(Map<String, Object> criteria, String orderProperty, Object lastOrderPropertyValue, boolean before);
	
	/**
	 * Get a list of user that liked an entry
	 * @param userId user identifier
	 * @param entryId entry identifier
	 * @param done goal entry or 'how i did it' entry
	 * @return List {@link FriendDTO}
	 */
	@Transactional(readOnly = true)	
	List<FriendDTO> getRandomEntryLikeList(Long userId, Long entryId, boolean done);
	
	/**
	 * Paging list of users that liked an entry
	 * @param entryId entry identifier
	 * @param isEntryDone goal entry or 'how i did it' entry
	 * @param pageNumber page number that will be loaded
	 * @return List {@link FriendDTO}
	 */
	@Transactional(readOnly = true)
	List<FriendDTO> getEntryLikePage(Long entryId, boolean isEntryDone, int pageNumber);
	
	@Transactional(readOnly = true)
	int countEntryLike(Long entryId, boolean isEntryDone);
	
	/**
	 * Paging list of users that cheered an entry
	 * @param entryId entry identifier
	 * @param isEntryDone goal entry or 'how i did it' entry
	 * @param pageNumber page number that will be loaded
	 * @return List {@link FriendDTO}
	 */
	@Transactional(readOnly = true)
	List<FriendDTO> getEntryCheerPage(Long entryId, boolean isEntryDone, int pageNumber);
}
